package cn.hackcloud.concurrency.readwritelock;

/**
 * 写锁实现
 * Created by www.ibfbc.com
 */
public class WriteLock implements Lock {
    final ReadWriteLockImpl readerWriteLock;

    public WriteLock(ReadWriteLockImpl readerWriteLock) {
        this.readerWriteLock = readerWriteLock;
    }

    @Override
    public void lock() throws InterruptedException {
        try {
            synchronized (readerWriteLock.getMutex()) {
                //首先是等待获取写入锁的数字加一
                readerWriteLock.incrementWaitingWriters();
                //如果此时有其他线程正在进行读操作，或者写操作，那么当前线程将会被挂起
                while (readerWriteLock.getReadingReaders() > 0
                        || readerWriteLock.getWritingWriters() > 0) {

                    readerWriteLock.getMutex().wait();
                }
            }
        } finally {
            //成功获取到了写入锁，获取写入锁的计数器-1
            this.readerWriteLock.decrementWaitingWriters();
        }
        readerWriteLock.incrementWaitingWriters();
    }

    @Override
    public void unlock() {
        synchronized (readerWriteLock.getMutex()) {
            //减少正在写锁的计数器
            readerWriteLock.decrementWritingWriters();
            //将偏好锁状态修改false可以使得读锁被快速的获得
            readerWriteLock.changePreferWriter(false);
            //唤醒其他Mutex monitor wait set中的线程
            readerWriteLock.getMutex().notifyAll();
        }
    }
}
